package com.flydog.mall.service.impl.pms;

import cn.hutool.core.collection.CollectionUtil;
import com.flydog.mall.common.api.PageResponse;
import com.flydog.mall.dto.PmsProductCategoryEntityParam;
import com.flydog.mall.dto.PmsProductCategoryParam;
import com.flydog.mall.dto.PmsProductCategoryWithChildrenItem;
import com.flydog.mall.entity.pms.PmsProductCategory;
import com.flydog.mall.entity.pms.PmsProductCategoryAttributeRelation;
import com.flydog.mall.repository.pms.PmsProductCategoryAttributeRelationRepository;
import com.flydog.mall.repository.pms.PmsProductCategoryRepository;
import com.flydog.mall.service.pms.PmsProductCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author Cao
 * @description 商品分类服务实现
 * @create 2021-03-27
 */
@Service
@Slf4j
public class PmsProductCategoryServiceImpl implements PmsProductCategoryService {

    @Autowired
    private PmsProductCategoryRepository categoryRepository;

    @Autowired
    private PmsProductCategoryAttributeRelationRepository categoryAttributeRelationRepository;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int create(PmsProductCategoryParam cate) {
        PmsProductCategory category = new PmsProductCategory();
        BeanUtils.copyProperties(cate, category);
        category.setLevel(parseLevel(category));
        PmsProductCategory savedCate = categoryRepository.save(category);
        if (!CollectionUtil.isEmpty(cate.getProductAttributeIdList())) {
            insertRelation(savedCate.getId(), cate.getProductAttributeIdList());
        }
        log.info("create category {}", savedCate.getId());
        return 1;
    }

    /**
     * TODO: 商品分类下有商品，应抛出异常，提示用户，阻止删除。
     *
     * @param ids 删除的分类ID列表
     * @return 删除的数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delete(List<Long> ids) {
        for (Long id : ids) {
            categoryAttributeRelationRepository.deleteByCategoryId(id);
            categoryRepository.deleteByParentId(id);
            categoryRepository.deleteById(id);
            log.info("delete cate {}", id);
        }
        return ids.size();
    }

    /**
     * TODO:更新商品信息中的分类名称信息
     *
     * @param id   分类的ID
     * @param cate 修改后的数据
     * @return 修改的数量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int update(Long id, PmsProductCategoryParam cate) {
        PmsProductCategory category = new PmsProductCategory();
        BeanUtils.copyProperties(cate, category);
        category.setId(id);
        category.setLevel(parseLevel(category));
        categoryRepository.save(category);
        //TODO:更新商品信息中的分类名称信息

        //更新分类筛选属性
        if (!CollectionUtil.isEmpty(cate.getProductAttributeIdList())) {
            categoryAttributeRelationRepository.deleteByCategoryId(category.getId());
            insertRelation(category.getId(), cate.getProductAttributeIdList());
        }
        log.info("更新商品分类{}", category);
        return 1;
    }

    @Override
    public PmsProductCategoryEntityParam getCategory(Long id) {
        Optional<PmsProductCategory> categoryRepo = categoryRepository.findById(id);
        PmsProductCategoryEntityParam result = new PmsProductCategoryEntityParam();
        if (categoryRepo.isPresent()) {
            PmsProductCategory cate = categoryRepo.get();
            BeanUtils.copyProperties(cate, result);
            List<PmsProductCategoryAttributeRelation> relations
                    = categoryAttributeRelationRepository.findByProductCategoryId(cate.getId());
            List<Long> attrList = new ArrayList<>();
            for (PmsProductCategoryAttributeRelation relation : relations) {
                attrList.add(relation.getProductAttributeId());
            }
            result.setProductAttributeIdList(attrList);
        }
        log.info("return product category {}", result.toString());
        return result;
    }

    @Override
    public List<PmsProductCategoryWithChildrenItem> listWithChildren() {
        List<PmsProductCategoryWithChildrenItem> result = new ArrayList<>();
        List<PmsProductCategory> categories = categoryRepository.findAll();
        for (PmsProductCategory cate : categories) {
            PmsProductCategoryWithChildrenItem item = new PmsProductCategoryWithChildrenItem();
            item.setName(cate.getName());
            item.setId(cate.getId());
            List<PmsProductCategory> child = categoryRepository.findByParentId(cate.getId());
            item.setChildren(child);
        }
        return result;
    }

    @Override
    public PageResponse<PmsProductCategory> list(Long parentId, Integer pageSize, Integer pageNum) {
        Page<PmsProductCategory> categories
                = categoryRepository.findByParentId(parentId,
                PageRequest.of(pageNum - 1, pageSize, Sort.by("sort")));
        return PageResponse.restPage(categories);
    }

    @Override
    public List<PmsProductCategory> list(Long parentId) {
        return categoryRepository.findByParentId(parentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateNavStatus(List<Long> ids, Integer navStatus) {
        for (Long id : ids) {
            categoryRepository.updateNavStatus(id, navStatus);
        }
        return ids.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateShowStatus(List<Long> ids, Integer showStatus) {
        for (Long id : ids) {
            categoryRepository.updateShowStatus(id, showStatus);
        }
        return ids.size();
    }

    private int parseLevel(PmsProductCategory cate) {
        if (cate.getParentId() == 0) {
            return 0;
        } else {
            Optional<PmsProductCategory> parent = categoryRepository.findById(cate.getParentId());
            return parent.map(pmsProductCategory -> pmsProductCategory.getLevel() + 1).orElse(0);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertRelation(Long cateId, List<Long> attributeList) {
        List<PmsProductCategoryAttributeRelation> relations = new ArrayList<>();
        for (Long attrId : attributeList) {
            PmsProductCategoryAttributeRelation relation = new PmsProductCategoryAttributeRelation();
            relation.setProductCategoryId(cateId);
            relation.setProductAttributeId(attrId);
            relations.add(relation);
        }
        relations = categoryAttributeRelationRepository.saveAll(relations);
        log.info("创建{}条分类筛选关系", relations.size());
    }
}
